package org.xhnews.charts;

import java.util.Vector;

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.XYPoint;

public class XYChartField extends Field implements DrawStyle {
	private int fieldWidth, fieldHeight, xCoord, yCoord;
	private int[] drawSizes;

	public XYChartField(int xVal, int yVal, int wVal, int hVal) {
		// Create a non focusable field.
		super(Field.NON_FOCUSABLE);

		// Set the x and y coordinates.
		xCoord = xVal;
		yCoord = yVal;

		// width and height.
		fieldWidth = wVal;
		fieldHeight = hVal;

	} // --- end of constructor ---

	public void setXCoord(int xVal) {
		if (xVal != xCoord) {
			xCoord = xVal;
			invalidate();
		}
	}

	public int getXCoord() {
		return xCoord;
	}

	public int getYCoord() {
		return yCoord;
	}

	public void setYCoord(int yCoord) {
		this.yCoord = yCoord;
	}

	public int getFieldWidth() {
		return fieldWidth;
	}

	public void setFieldWidth(int fieldWidth) {
		this.fieldWidth = fieldWidth;
	}

	public int getFieldHeight() {
		return fieldHeight;
	}

	public void setFieldHeight(int fieldHeight) {
		this.fieldHeight = fieldHeight;
	}

	public void draw_the_grid(Graphics this_g, Vector these_labels) {
		double rounded_max;
		double rounded_min;
		Object curElt;
		String[] cur_elt_array;
		int left_margin_d, right_margin_d;

		// work out the margins -- only 2 items to avoid confusion
		switch (these_labels.size()) {
		// set it up for 1-elt chart
		case 1: // work out margin space according to max value to be plotteed
			curElt = these_labels.elementAt(0);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
			left_margin_d = getFont().getAdvance(Double.toString(rounded_max));

			// keep the position for later drawing
			int[] tmp_draw_sizes = { 2 + left_margin_d, 25,
					fieldWidth - 2 + left_margin_d, fieldHeight - 25 - 5 };
			drawSizes = tmp_draw_sizes; // keep it for later processing

			break;

		case 2: // same as above but now left and right margins

			curElt = these_labels.elementAt(0);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
			left_margin_d = getFont().getAdvance(Double.toString(rounded_max));

			curElt = these_labels.elementAt(1);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
			right_margin_d = getFont().getAdvance(Double.toString(rounded_max));

			// keep the position for later drawing
			int[] tmp_draw_sizes1 = { 2 + left_margin_d, 25,
					fieldWidth - left_margin_d - right_margin_d - 4,
					fieldHeight - 25 - 5 };
			drawSizes = tmp_draw_sizes1; // keep it for later processing

			break;
		default:
			// error on allowed dimensions
		}

		// with the margins worked out draw the plotting grid
		this_g.fillRoundRect(drawSizes[0], drawSizes[1], drawSizes[2],
				drawSizes[3], 1, 1);

		this_g.setColor(Color.LIGHTGREY);

		this_g.drawRect(drawSizes[0], drawSizes[1], drawSizes[2], drawSizes[3]);

		// draw the mesh
		for (int i = 1; i < 5; i++) {
			this_g.drawLine(drawSizes[0],
					drawSizes[1] + (i * drawSizes[3] / 5), drawSizes[0]
							+ drawSizes[2], drawSizes[1]
							+ (i * drawSizes[3] / 5));
			this_g.drawLine(drawSizes[0] + (i * drawSizes[2] / 5),
					drawSizes[1], drawSizes[0] + (i * drawSizes[2] / 5),
					drawSizes[1] + drawSizes[3]);
		}

		// print the labels and we are good
		switch (these_labels.size()) {
		case 1:
			this_g.setColor(Color.RED);
			curElt = these_labels.elementAt(0);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
//			print_axis_values_4_grid(this_g, "mph", Double
//					.toString(rounded_max), "0", cur_elt_array[1], 2, 0);

			break;
		case 2:
			this_g.setColor(Color.RED);
			curElt = these_labels.elementAt(0);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
//			print_axis_values_4_grid(this_g, "mph", Double
//					.toString(rounded_max), "0", cur_elt_array[1], 2, 0);

			this_g.setColor(Color.BLUE);
			curElt = these_labels.elementAt(1);
			cur_elt_array = (String[]) curElt;
			rounded_max = Math.ceil(Double.valueOf(cur_elt_array[0])
					.doubleValue());
//			print_axis_values_4_grid(this_g, "sec", Double
//					.toString(rounded_max), "0", cur_elt_array[1], drawSizes[0]
//					+ drawSizes[2] + 3, 1);
			break;

		} // --- ed of draw_the_grid ---
	}

	public void paint(Graphics graphics) {
		// set background of our field
		graphics.setColor(Color.AQUA);
		graphics.fillRoundRect(0, 0, getWidth(), getHeight(), 15, 15);
		graphics.setColor(Color.LIGHTBLUE);
		graphics.drawRoundRect(0, 0, getWidth(), getHeight(), 15, 15);
		graphics.setColor(Color.BEIGE);

		// labels_vector arg has [maxVal, label] objects
//		draw_the_grid(graphics, labels_vector);

	} // --- end of paint---

	private XYPoint scale_point(int this_x, double this_y, XYPoint drawPoint,
			int scr_x, int scr_y, int scr_width, int src_height, double maxX,
			double minX, double maxY, double minY) {
		int temp_x, temp_y;
		XYPoint temp = new XYPoint();

		if (maxY == minY) // skip bad data
			return null;

		// don't touch it if bad data
		try {
			// if (! ( this_x == null) )
			temp_x = scr_x
					+ (int) (((double) this_x - minX) * ((double) scr_width / (maxX - minX)));
			temp_y = scr_y
					+ (int) ((maxY - this_y) * ((double) src_height / (maxY - minY)));

			temp.x = temp_x;
			temp.y = temp_y;
			drawPoint = temp;

		} catch (Exception e) {

			return (null);
		}

		return temp;

	} // --- end of scale_point --

	public boolean plot_array_list(Graphics this_g, Vector this_array_list,
			Vector these_labels, String this_title) {
		int lRow;
		int nParms;
		int i, points_2_plot, shifted_idx;
		int prev_x, prev_y;
		int cur_x = 0, cur_y = 0;
		// Dim ShowMarker As Object
		XYPoint cur_point = new XYPoint();
		cur_point.set(0, 0);

		double cur_maxX, cur_minX, cur_maxY = 20, cur_minY = 0, cur_rangeY;
		int cur_start_x, cur_points_2_plot;

		Object curElt;
		String[] cur_elt_array;

		draw_the_grid(this_g, these_labels);

		try {
			points_2_plot = this_array_list.size();

			// 'Work it out so it prints the scrolled section if required
			cur_start_x = 0;
			cur_points_2_plot = points_2_plot;
			cur_maxX = cur_points_2_plot;
			cur_minX = 0;

			// 'Create the plot points for this series from the ChartPoints
			// array:

			curElt = this_array_list.elementAt(0);
			cur_elt_array = (String[]) curElt;

			// the lines plotted have to look good
			this_g.setDrawingStyle(Graphics.DRAWSTYLE_AALINES, true);

			// skip 1st elt of array as it is the x-axis value
			for (nParms = 1; nParms < cur_elt_array.length; nParms++) {
				curElt = these_labels.elementAt(nParms - 1);
				cur_elt_array = (String[]) curElt;
				cur_maxY = Integer.parseInt(cur_elt_array[0]);

				curElt = this_array_list.elementAt(cur_start_x);
				cur_elt_array = (String[]) curElt;

				cur_point = scale_point(Integer.parseInt(cur_elt_array[0]),
						Double.parseDouble(cur_elt_array[nParms]), cur_point,
						drawSizes[0], drawSizes[1], drawSizes[2], drawSizes[3],
						cur_maxX, cur_minX, cur_maxY, cur_minY);
				cur_x = cur_point.x;
				cur_y = cur_point.y;

				prev_x = cur_x;
				prev_y = cur_y;

				switch (nParms) {
				case 1:
					this_g.setColor(Color.RED);
					break;
				case 2:
					this_g.setColor(Color.BLUE);
					break;
				}

				// go and plot this parm
				for (lRow = cur_start_x + 1; lRow < cur_start_x
						+ cur_points_2_plot; lRow++) {
					curElt = this_array_list.elementAt(lRow);
					cur_elt_array = (String[]) curElt;

					if (cur_elt_array[0] == null)
						cur_elt_array[0] = "0";

					if (!(cur_elt_array[nParms] == null)) // skip bad one
					{

						cur_point = scale_point(Integer
								.parseInt(cur_elt_array[0]), Double
								.parseDouble(cur_elt_array[nParms]), cur_point,
								drawSizes[0], drawSizes[1], drawSizes[2],
								drawSizes[3], cur_maxX, cur_minX, cur_maxY,
								cur_minY);

						cur_x = cur_point.x;
						cur_y = cur_point.y;

						this_g.drawLine(prev_x, prev_y, cur_x, cur_y);
						prev_x = cur_x;
						prev_y = cur_y;

					} // if end of this_array(lRow, nParms - 1)<> nothing

				} // end of for lrow

			} // end of for nParmns

			invalidate();
			return (true);
		} catch (Exception e) {
			return (false);
			// Console.out some message for debugging
		}

	} // --- end of plot_array_list ---


	protected void layout(int width, int height) {
		// TODO Auto-generated method stub
		
	}
}
